# 类与类的继承

# 类的实例化

类的实例化可参考https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Inheritance_and_the_prototype_chain (opens new window)

// 因此,当你执行:
var o = new Foo()

// JavaScript 实际上执行的是:
var o = new Object()
o.__proto__ = Foo.prototype
Foo.call(o)

# 类的继承

ES6 提供了类继承相关的语法,我们直到类的继承是基于原型的,那么如果用 ES5,我们应该怎么些呢?

class A {
  constructor () {
    console.log(this)
  }
  a () {}
}

class B extends A {
  b () {}
}

class C extends B {
  constructor () {
    super()
    console.log(arguments)
  }
  c () {}
}

const c = new C()

# babel 编译后的代码

function _possibleConstructorReturn(self, call) {
  if (call && (typeof call === 'object' || typeof call === 'function')) {
    return call
  }
  return _assertThisInitialized(self)
}

function _assertThisInitialized(self) {
  if (self === undefined) {
    throw new ReferenceError("this hasn't been initialised - super() hasn't been called")
  }
  return self
}

function _getPrototypeOf(o) {
  return o.__proto__
}

function _inherits(subClass, superClass) {
  if (typeof superClass !== 'function' && superClass !== null) {
    throw new TypeError('Super expression must either be null or a function')
  }
  subClass.prototype = Object.create(superClass && superClass.prototype, {
    constructor: {
      value: subClass,
      writable: true,
      configurable: true
    }
  })

  if (superClass) subClass.__proto__ = superClass
}

function _classCallCheck(instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError('Cannot call a class as a function')
  }
}

function _defineProperties(target, props) {
  for (var i = 0; i < props.length; i++) {
    var descriptor = props[i]
    descriptor.enumerable = descriptor.enumerable || false
    descriptor.configurable = true
    if ('value' in descriptor) descriptor.writable = true
    Object.defineProperty(target, descriptor.key, descriptor)
  }
}

function _createClass(Constructor, protoProps, staticProps) {
  if (protoProps) _defineProperties(Constructor.prototype, protoProps)
  if (staticProps) _defineProperties(Constructor, staticProps)
  return Constructor
}

var A =
  /* #__PURE__ */
  (function() {
    function A() {
      _classCallCheck(this, A)

      console.log(this)
    }

    _createClass(A, [
      {
        key: 'a',
        value: function a() {}
      }
    ])

    return A
  })()

var B =
  /* #__PURE__ */
  (function(_A) {
    _inherits(B, _A)

    function B() {
      _classCallCheck(this, B)

      return _possibleConstructorReturn(this, _getPrototypeOf(B).apply(this, arguments))
    }

    _createClass(B, [
      {
        key: 'b',
        value: function b() {}
      }
    ])

    return B
  })(A)

var C =
  /* #__PURE__ */
  (function(_B) {
    _inherits(C, _B)

    function C() {
      var _this

      _classCallCheck(this, C)

      _this = _possibleConstructorReturn(this, _getPrototypeOf(C).call(this))
      console.log(arguments)
      return _this
    }

    _createClass(C, [
      {
        key: 'c',
        value: function c() {}
      }
    ])

    return C
  })(B)

var c = new C()

# B 继承 A 简化

function A() {
  this.myA = 'a'
}

A.prototype.a = function() {
  console.log('A-a')
}

function B() {
  const _this = A.apply(this, arguments) || this
  _this.myB = 'b'
  return _this
}

B.prototype.__proto__ = A.prototype
B.__proto__ = A

# instanceof 与 isPrototypeOf 的区别

b instanceof B // b.__proto__ === B.prototype 一直查找__proto__是否为B.prototype
B.isPrototypeOf(b) // b.__proto__ === B 一直查找 __proto__ 上的值是否为B

B.prototype.isPrototypeOf(b) // 相当于 b instanceof B